package com.example.test_gen.fastorm;

import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class QueryObj {

    List<TableField> selectList = new ArrayList();
    List<TableField> groupList = new ArrayList();
    List<WhereItem> whereList = new ArrayList();
    BaseProxy baseProxy;

    public QueryObj from(BaseProxy baseProxy) {
        this.baseProxy = baseProxy;
        return this;
    }

    public QueryObj where(TableField column, ValueType valueType) {
        this.whereList.add(new WhereItem(column, valueType));
        return this;
    }

    public QueryObj limit() {
        return this;
    }

    public QueryObj groupBy(TableField column) {
        this.groupList.add(column);
        return this;
    }

    public <T> List<T> toList(Class<T> clazz) {
        List<Object> valueArr = new ArrayList<>();

        String fieldStr = getFieldStr();
        String whereStr = getWhereStr(valueArr);
        String groupStr = getGroupStr();

        String sql = "SELECT " + fieldStr + " FROM " + baseProxy.getTableName() + whereStr + groupStr + " limit 2";
        System.out.println(sql);
        System.out.println(valueArr);

        return JdbcTemplate().query(sql, valueArr.toArray(), new BeanPropertyRowMapper<>(clazz));
    }

    private JdbcTemplate JdbcTemplate() {
        return SpringContextUtils.getBean("jdbcTemplate", JdbcTemplate.class);
    }

    private String getFieldStr() {
        List<String> whereArr = new ArrayList<>();
        for (int i = 0; i < selectList.size(); i++) {
            TableField whereItem = selectList.get(i);
            String fieldName = whereItem.fieldName;
            String newFieldName = whereItem.newFieldName;

            if (newFieldName.equals("")) {
                whereArr.add(fieldName);
            } else {
                whereArr.add(fieldName + " AS " + newFieldName);
            }
        }

        String whereStr = "*";
        if (whereArr.size() > 0) {
            whereStr = String.join(",", whereArr);
        }

        return whereStr;
    }

    private String getGroupStr() {
        List<String> whereArr = new ArrayList<>();
        for (int i = 0; i < groupList.size(); i++) {
            TableField whereItem = groupList.get(i);
            String fieldName = whereItem.fieldName;
            whereArr.add(fieldName);
        }

        String whereStr = "";
        if (whereArr.size() > 0) {
            whereStr += " GROUP BY ";
            whereStr += String.join(",", whereArr);
        }

        return whereStr;
    }

    private String getWhereStr(List<Object> valueArr) {
        List<String> whereArr = new ArrayList<>();
        for (int i = 0; i < whereList.size(); i++) {
            WhereItem whereItem = whereList.get(i);
            String fieldName = whereItem.tableField.fieldName;
            String type = whereItem.valueType.type;
            Object fieldVal = whereItem.valueType.fieldVal;

            if (type.equals("=") || type.equals("!=") || type.equals("<") || type.equals("<=") || type.equals(">") || type.equals(">=")) {
                whereArr.add(fieldName + type + "?");
                valueArr.add(fieldVal);
            }

            if (type.equals("IN") || type.equals("NOT IN")) {
                List<Object> fieldValNew = (List<Object>) fieldVal;
                whereArr.add(fieldName + " " + type + " (" + fieldValNew.stream().map(item -> "?").collect(Collectors.joining(",")) + ")");
                valueArr.addAll(fieldValNew);
            }

            if (type.equals("BETWEEN") || type.equals("NOT BETWEEN")) {
                List<Object> fieldValNew = (List<Object>) fieldVal;
                whereArr.add(fieldName + " " + type + " " + fieldValNew.stream().map(item -> "?").collect(Collectors.joining(" and ")) + "");
                valueArr.addAll(fieldValNew);
            }
        }

        String whereStr = "";
        if (whereArr.size() > 0) {
            whereStr += " WHERE ";
            whereStr += String.join(" AND ", whereArr);
        }

        return whereStr;
    }
}